home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 466_01 / SRC / CMDARGS.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  12.9 KB  |  550 lines

  1. #include <afx.h>
  2. #include <afxtempl.h>
  3. #ifdef _DEBUG
  4. #include <ostream.h>
  5. #endif
  6. #include "errmsg.h"
  7. #include "parse.h"
  8. #include "topiclog.h"
  9. #include "fmtspec.h"
  10. #include "docexpr.h"
  11. #include "cmdargs.h"
  12.  
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #endif
  16.  
  17. int GetArgs(CStrArray &asArgs, char **argv, int argc)
  18. {
  19. TRY
  20. {
  21.     CFile file;
  22.     CFileException e;
  23.     char *szBuf;
  24.     const char *szStart;
  25.     const char *sz;
  26.     long lcb;
  27.     BOOL fQuoteBreak;
  28.     int nRet = 0;
  29.     int nArgs = 0;
  30.  
  31.     // Collect command-line arguments, including response files.
  32.  
  33.     for(int i = 1; i < argc; i++)
  34.     {
  35.         szBuf = NULL;
  36.  
  37.         if(argv[i][0] == '@')
  38.         {
  39.             // Open the response file and read contents.
  40.  
  41.             if(!file.Open(&argv[i][1], CFile::modeRead, &e))
  42.                 return e.m_cause;
  43.  
  44.             lcb = file.Seek(0, CFile::end);
  45.             szBuf = new char[lcb+1];
  46.  
  47.             file.SeekToBegin();
  48.     
  49.             file.Read(szBuf, (UINT)lcb);
  50.             file.Close();
  51.  
  52.             szBuf[lcb] = '\0';
  53.  
  54.             // Parse contents. 
  55.  
  56.             sz = szBuf;
  57.             fQuoteBreak = FALSE;
  58.  
  59.               while(*sz)
  60.               {
  61.                 // Find end of string and null-terminate.
  62.  
  63.                 szStart = sz = EatWhite(sz);
  64.  
  65.                 // String break on space - or delimited
  66.                 // by double quotation marks
  67.  
  68.                 if(fQuoteBreak || *sz == chQuote)
  69.                 {
  70.                     if(fQuoteBreak)
  71.                         fQuoteBreak = FALSE;
  72.                     else
  73.                         szStart++, sz++;
  74.  
  75.                     while(*sz && *sz != chNewline && *sz != chQuote)
  76.                         sz++;
  77.  
  78.                     if(*sz != chQuote)
  79.                     {
  80.                         nRet = errMismatchedResponseQuotes;
  81.                         goto ExitError;
  82.                     }
  83.                 }
  84.                 else
  85.                 {
  86.                     while(*sz && !isspace(*sz) && *sz != chQuote)
  87.                         sz++;
  88.  
  89.                     fQuoteBreak = (*sz == chQuote);
  90.                 }
  91.  
  92.                 // Add the entry
  93.  
  94.                 if(*szStart)
  95.                 {
  96.                     asArgs.SetSize(++nArgs);
  97.                     asArgs[nArgs-1] = new CString(szStart, sz-szStart);
  98.                 }
  99.  
  100.                 // Advance past newline if present.
  101.  
  102.                 if(*sz)
  103.                     sz++;
  104.               }
  105.  
  106.             delete szBuf;
  107.  
  108.             szBuf = NULL;
  109.         }
  110.         else
  111.         {
  112.             asArgs.SetSize(++nArgs);
  113.             asArgs[nArgs-1] = new CString(argv[i]);
  114.         }
  115.     }
  116.  
  117. ExitError:
  118.     if(szBuf)
  119.         delete szBuf;
  120.     return nRet;
  121. }
  122. CATCH(CFileException, e)
  123. {
  124.     return e->m_cause;
  125. }
  126. AND_CATCH(CMemoryException, e)
  127. {
  128.     return errMemory;
  129. }
  130. END_CATCH
  131. }
  132.  
  133.  
  134.  
  135.  
  136. /*
  137. @func Parses a command-line constant definition, in the form:
  138.  
  139. /Dname=constant_text
  140. /D name=constant_text
  141.  
  142. @rdesc Returns 0 if successful or 1 if an error occurs.
  143. */
  144.  
  145. int GetCmdLineConstant(
  146.     FormatInfo &fmt,                                 //@parm Where to put constant defs
  147.     const char *szArg,                              //@parm Arg containing /D directive
  148.     CStrArray &asArgs,     //@parm Rest of the command line arguments
  149.     int &i)                                         //@parm Array index
  150. {
  151. TRY
  152. {
  153.     const char *szTag;
  154.     const char *szText;
  155.     CFmtConst *pNew;
  156.     int nArgsCount = asArgs.GetSize();
  157.  
  158.     // Find where the constant def is.
  159.  
  160.     if(szArg[2])
  161.     {
  162.         szTag = &szArg[2];
  163.     }
  164.     else
  165.     {
  166.         if(i == nArgsCount-1)
  167.             return 1;
  168.  
  169.         szTag = *asArgs[++i];
  170.     }
  171.  
  172.     // Find the equal sign.
  173.  
  174.     for(int i = 0; szTag[i] != chEqual && i < MAXTAGSIZE; i++);
  175.     if(szTag[i] != chEqual)
  176.         return errCmdSyntaxDefine;
  177.  
  178.     // Seal off the constant name, advance to the constant text,
  179.     // alloc mem for everything.
  180.  
  181.     szText = szTag+i+1;
  182.  
  183.     CString sTag;
  184.     char *sz = sTag.GetBufferSetLength(i+1);
  185.     memcpy(sz, szTag, i);
  186.     sz[i] = '\0';
  187.     sTag.ReleaseBuffer;
  188.  
  189.     pNew = new CFmtConst(sTag, szText);
  190.  
  191.     // Add constant def to the options.
  192.  
  193.     fmt.constant.Add(pNew);
  194.  
  195.     return 0;
  196. }
  197. CATCH(CMemoryException, e)
  198. {
  199.     return errMemory;
  200. }
  201. END_CATCH
  202. }
  203.  
  204.  
  205. int Assign(
  206.     CString     &sTarget,
  207.     const char    *szCurArg,
  208.     CStrArray   &asArgs,
  209.     int         &i,
  210.     int         nArgsCount,
  211.     BOOL        bConcat)
  212. {
  213.     if(*szCurArg)
  214.     {
  215.         if(bConcat)
  216.             sTarget += szCurArg;
  217.         else
  218.             sTarget = szCurArg;
  219.     }
  220.     else
  221.     {
  222.         if(i == nArgsCount-1)
  223.             return errCmdSyntaxExpectedFlagFollowup;
  224.  
  225.         if(bConcat)
  226.             sTarget += *asArgs[++i];
  227.         else
  228.             sTarget = *asArgs[++i];
  229.     }
  230.  
  231.     return 0;
  232. }
  233.  
  234.  
  235. /*-----------------------------------------------------------------------
  236.     @doc EXTERNAL AUTODUCK
  237.         
  238.     @func int | ParseArgs | Parses command-line arguments and fills
  239.         <t RUNOPTIONS> structure with runtime options.
  240.             
  241.     @rdesc Returns 0 if successful or 1 if a syntax error in the command
  242.         line.
  243. */
  244.  
  245. int ParseArgs(
  246.     CStrArray &asArgs,          //@parm Array of command line args
  247.     RUNOPTIONS &run,               //@parm Options structure to fill
  248.     FormatInfo &fmt,            //@parm Format information file
  249.     const char*szDefaultFmtFilename)     //@parm Default format file
  250. {
  251.     const char *szArg;
  252.     int i, nArgsCount;
  253.     int nRet;
  254.     int nInput = 0;
  255.     int nFmt = 0;
  256.  
  257.     CString sMainFmtFile(szDefaultFmtFilename);
  258.     CString *psNewFmtFile;
  259.  
  260.     nArgsCount = asArgs.GetSize();
  261.     ZeroMem(&run.nOptions, sizeof(run.nOptions));
  262.  
  263.     run.nExampleTabSize = 8;
  264.  
  265.     for(i = 0; i < nArgsCount; i++)
  266.     {
  267.         szArg = *asArgs[i];
  268.  
  269.         switch (szArg[0])
  270.         {
  271.         case '/':
  272.         case '-':
  273.             switch( szArg[1] )
  274.             {
  275.             case '?':
  276.             case 'H':
  277.             case 'h':
  278.                 return errCmdSyntaxHelp;
  279.  
  280.             case 'v':
  281.             case 'V':
  282.                 run.nOptions.Verbose = TRUE;
  283.                 break;
  284.  
  285.             case 'e':
  286.             case 'E':
  287.                 run.nOptions.NoEmptyWarnings = TRUE;
  288.                 break;
  289.  
  290.             case 'u':
  291.             case 'U':
  292.                 run.nOptions.Unsorted = TRUE;
  293.                 break;
  294.  
  295.             case 'n':
  296.             case 'N':
  297.                 run.nOptions.NoOutput = TRUE;
  298.                 break;
  299.  
  300.             case 'a':
  301.             case 'A':
  302.                 run.nOptions.Concat = TRUE;
  303.                 break;
  304.  
  305.             case 'x':
  306.             case 'X':
  307.                 nRet = Assign(run.sDocID, &szArg[2], asArgs, i, nArgsCount, TRUE);
  308.                 if(nRet)
  309.                     return nRet;
  310.  
  311.                 run.sDocID += chSpace;
  312.  
  313.                 break;
  314.  
  315.             case 'r':
  316.             case 'R':
  317.                 if(szArg[2] && (szArg[3] == '\0'))
  318.                 {
  319.                     switch(szArg[2])
  320.                     {
  321.                     case 'd':
  322.                     case 'D':
  323.                         run.sOutputType = "doc";
  324.                         continue;
  325.  
  326.                     case 'h':
  327.                     case 'H':
  328.                         run.sOutputType = "help";
  329.                         continue;
  330.                     }
  331.                 }
  332.  
  333.                 nRet = Assign(run.sOutputType, &szArg[2], asArgs, i, nArgsCount, FALSE);
  334.                 if(nRet)
  335.                     return nRet;
  336.  
  337.                 break;
  338.  
  339.             case 't':
  340.             case 'T':
  341.                 if(!isdigit(szArg[2]))
  342.                     return errCmdSyntaxTab;
  343.  
  344.                 run.nExampleTabSize = atoi(&szArg[2]);
  345.  
  346.                 break;
  347.  
  348.             case 'o':
  349.             case 'O':
  350.                 nRet = Assign(run.sOutputFile, &szArg[2], asArgs, i, nArgsCount, FALSE);
  351.                 if(nRet)
  352.                     return nRet;
  353.  
  354.                 break;
  355.                 
  356.             case 'f':
  357.             case 'F':
  358.                 nRet = Assign(sMainFmtFile, &szArg[2], asArgs, i, nArgsCount, FALSE);
  359.                 if(nRet)
  360.                     return nRet;
  361.  
  362.                 break;
  363.                 
  364.             case 's':
  365.             case 'S':
  366.                 psNewFmtFile = new CString;
  367.                 nRet = Assign(*psNewFmtFile, &szArg[2], asArgs, i, nArgsCount, FALSE);
  368.                 if(nRet)
  369.                 {
  370.                     delete psNewFmtFile;
  371.                     return nRet;
  372.                 }
  373.  
  374.                 run.asFmtFiles.SetSize(++nFmt);
  375.                 run.asFmtFiles[nFmt-1] = psNewFmtFile;
  376.  
  377.                 break;
  378.                 
  379.             case 'l':
  380.             case 'L':
  381.                 nRet = Assign(run.sLogFileOut, &szArg[2], asArgs, i, nArgsCount, FALSE);
  382.                 if(nRet)
  383.                     return nRet;
  384.  
  385.                 break;
  386.                 
  387.             case 'c':
  388.             case 'C':
  389.                 nRet = Assign(run.sLogFileIn, &szArg[2], asArgs, i, nArgsCount, FALSE);
  390.                 if(nRet)
  391.                     return nRet;
  392.  
  393.                 break;
  394.                 
  395.             case 'd':
  396.             case 'D':
  397.                 nRet = GetCmdLineConstant(fmt, szArg, asArgs, i);
  398.                 if(nRet)
  399.                     return nRet;
  400.                     
  401.                 break;
  402.  
  403.             default:
  404.                 return errCmdSyntaxUnknownFlag;
  405.             }
  406.  
  407.             break;
  408.         
  409.         default:
  410.             run.asInputFiles.SetSize(++nInput);
  411.             run.asInputFiles[nInput-1] = asArgs[i];
  412.             asArgs[i] = NULL;
  413.             break;
  414.         }
  415.     }
  416.  
  417.     if(run.asInputFiles.GetSize() == 0)
  418.         return errNoFiles;
  419.  
  420.     if(run.sOutputType.IsEmpty())
  421.         run.sOutputType = "doc";
  422.  
  423.     char *sz2;
  424.     char *sz = run.sDocID.GetBuffer(run.sDocID.GetLength()+1);
  425.     nRet = run.exprExtract.Set(sz, sz2);
  426.     run.sDocID.ReleaseBuffer();
  427.  
  428.     run.asFmtFiles.SetSize(++nFmt);
  429.     run.asFmtFiles[nFmt-1] = new CString(sMainFmtFile);
  430.  
  431.     if(nRet)
  432.         return nRet;
  433.  
  434.     return 0;
  435. }
  436.  
  437. /*-----------------------------------------------------------------------
  438.     @doc EXTERNAL AUTODUCK
  439.         
  440.     @func void | Usage | Prints usage statement on <p stderr>.
  441.         
  442.     @parm char * | szName | Specifies a null-terminated string containing
  443.         the name of this program.
  444.  
  445.     @rdesc Void.
  446. */
  447. void Usage(const char * szName, const char *szFmtFilename)
  448. {
  449.     fprintf(stderr, "%s [/v] [/e] [/n] [/a] [/u] [/r[dh]] [/t[0-9]]\n\t[/o filename] [/l filename]\n\t[/f filename] [/c filename] \n\t[[/x id]...] [[/d name=text]...] files\n\n", szName);
  450.     fprintf(stderr, "[/v]               Verbose\n");
  451.     fprintf(stderr, "[/e]               Suppress warnings about empty fields.\n");
  452.     fprintf(stderr, "[/n]               No output (extract only - only generate log file)\n");
  453.     fprintf(stderr, "[/a]               Append output to existing file\n");
  454.     fprintf(stderr, "[/u]               Don't sort topics\n");
  455.     fprintf(stderr, "[/rd]              Generate \"doc\" output (default)\n");
  456.     fprintf(stderr, "[/rh]              Generate \"help\" output\n");
  457.     fprintf(stderr, "[/r output]        Generate specified output type\n");
  458.     fprintf(stderr, "[/x expression]    Extract topics matching expression\n");
  459.     fprintf(stderr, "[/t[0-9]]          Set tab size for example tags (default is 8)\n");
  460.     fprintf(stderr, "[/o file]          Create (or append to) RTF file <file>\n");
  461.     fprintf(stderr, "[/l file]          Create (or append to) topic log <file>\n");
  462.     fprintf(stderr, "[/f file]          Use format file <file> (default is %s)\n", szFmtFilename);
  463.     fprintf(stderr, "[/s file]          Use supplemental format file <file>\n");
  464.     fprintf(stderr, "[/c file]          Use topic log <file>\n");
  465.     fprintf(stderr, "[/d name=text]     Define constant <name> as <text>\n");
  466. }
  467.  
  468.  
  469. int SetRtOptions(
  470.     RUNOPTIONS &run,
  471.     FormatInfo &fmt,
  472.     char **argv,
  473.     int argc,
  474.     const char *szDefaultFmtFilename)
  475. {
  476.     CStrArray asArgs;
  477.     int nRet;
  478.     int i, nArgs;
  479.  
  480.     nRet = GetArgs(asArgs, argv, argc);
  481.     if(nRet)
  482.     {
  483.         PrintError(NULL, 0, nRet);
  484.         return nRet;
  485.     }
  486.  
  487.     nArgs = asArgs.GetSize();
  488.    
  489.     nRet = ParseArgs(asArgs, run, fmt, szDefaultFmtFilename);
  490.     if(errCmdSyntaxHelp == nRet)
  491.     {
  492.         Usage(argv[0], szDefaultFmtFilename);
  493.     }
  494.     else if(nRet)
  495.     {
  496.         PrintError(NULL, NO_LINE, nRet);
  497.     }
  498.  
  499.     for(i = 0; i < nArgs; i++)
  500.     {
  501.         if(asArgs[i])
  502.             delete asArgs[i];
  503.     }
  504.  
  505.     return nRet;
  506. }
  507.  
  508.  
  509. #ifdef _DEBUG
  510. void DumpOptions(RUNOPTIONS &run)
  511. {
  512.     cout << "RUNOPTIONS dump:\n";
  513.  
  514.     cout << "\tOptions:\n";
  515.     cout << "\t\tVerbose  " << run.nOptions.Verbose << "\n";         
  516.     cout << "\t\tNoEmptyWarnings  " << run.nOptions.NoEmptyWarnings << "\n";         
  517.     cout << "\t\tUnsorted  " << run.nOptions.Unsorted << "\n";
  518.     cout << "\t\tNoOutput  " << run.nOptions.NoOutput << "\n";
  519.     cout << "\t\tConcat  " << run.nOptions.Concat << "\n";
  520.  
  521.     cout << "\tnExampleTabSize  " << run.nExampleTabSize << "\n";
  522.      cout << "\tsDocID  " << run.sDocID << "\n";
  523.     cout << "\tsOutputType  " << run.sOutputType << "\n";              
  524.     cout << "\tsOutputFile  " << run.sOutputFile << "\n";              
  525.     cout << "\tsLogFileIn  " << run.sLogFileIn << "\n";               
  526.     cout << "\tsLogFileOut  " << run.sLogFileOut << "\n";              
  527.  
  528.     int nFiles = run.asInputFiles.GetSize();
  529.     int i;
  530.     const char *pch;
  531.  
  532.     cout << "\n\t" << nFiles << " input files, they are:\n";
  533.     for(i = 0; i < nFiles; i++)
  534.     {
  535.         pch = *run.asInputFiles[i];
  536.         cout << "\t\t" << pch << "\n";
  537.     }
  538.     cout << endl;
  539.  
  540.     nFiles = run.asFmtFiles.GetSize();
  541.     cout << "\n\t" << nFiles << " format files, they are:\n";
  542.     for(i = 0; i < nFiles; i++)
  543.     {
  544.         pch = *run.asFmtFiles[i];
  545.         cout << "\t\t" << pch << "\n";
  546.     }
  547.     cout << endl;
  548. }
  549. #endif
  550.